
module LanguageDef where
data NodeType
    = RootNode                  -- [relationDef]
    | RelationDefNode String    -- varlist cstraint
    | EqualNode                 -- expr1 expr2
    | AndNode 
    | OrNode 
    | ForAllNode                -- dexpr vvar cstraint
    | ExistsNode                -- dexpr vvar cstraint
    | Exists'Node               -- dexpr vvar cstraint
    | OneNode                   -- dexpr vvar cstraint
    | One'Node                  -- kexpr dexpr vvar cstraint
    | LetNode                   -- var expr cstraint/expr
    | ProtectNode               -- var cstraint
    | TestNode 
    | NotNode 
    | RelationRefNode String    -- exprlist
    | DictGetNode 
    | IsConstNode               -- expr
    | StringConstNode String
    | IntConstNode Int
    | NullConstNode
    | TrueConstNode
    | FalseConstNode
    | VarNode String
    | VarListNode 
    | ETraceNode String         -- variableList expr
    | CTraceNode String     
    | AllVarNode                -- auxiliary node for trace
    | HaskellVarNode String     -- for assisting code generation
    | LeteNode -- for assisting code generation 
    deriving (Show, Eq)

data Node = Node {
        nodeType :: NodeType,
        pos :: Pos,
        children :: [Node]
    }
    
replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace [] _ _ = []
replace s find repl =
    if take (length find) s == find
        then repl ++ (replace (drop (length find) s) find repl)
        else [head s] ++ (replace (tail s) find repl)

instance Show Node where
    showsPrec _ Node{nodeType=nodeType, pos=Pos x y , children=children} =
        showString "\n". 
        shows nodeType. showString "(". shows x. showString ",". shows y. 
        showString ")". showString (replace (foldl (++) "" (map show children)) "\n" "\n ")      
    
getNodeType Node{nodeType=aType} = aType
getNodePos Node{pos = aPos} = aPos
getNodeChildren Node{children = c} = c 
    
data Pos = Pos Int Int
    deriving (Show)
    
pos2String :: Pos -> ShowS
pos2String (Pos line col) = 
    showString "(".shows line.showString ":".shows col.showString ")"  